package com.css.dynamic.dynamicRoute;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.collection.CollUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 郭辉
 * @className DynamicRouteConfig
 * @description 动态路由的配置
 * @date 2022/9/19 19:33
 * @company 海康威视
 * @since 1.0.0
 */
@Slf4j
@Component
@AllArgsConstructor
public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {

    private final RedisTemplate redisTemplate;

    /**
     * 动态路由入口
     * <p>
     * 1. 先从内存中获取
     * 2. 为空加载Redis中数据
     * 3. 更新内存
     *
     * @return
     */
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        //获取全部缓存对象
        List<RouteDefinitionVo> routeList = RouteCacheHolder.getRouteList();
        if (CollUtil.isNotEmpty(routeList)) {
            System.out.println("内存 ： {}， {}" + routeList.size() + routeList);
            return Flux.fromIterable(routeList);
        }
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
        List<RouteDefinitionVo> values = redisTemplate.opsForHash().values("gateway_route_key");
        System.out.println("redis 中路由定义条数： {}， {}" + values.size() + values);
        RouteCacheHolder.setRouteList(values);
        return Flux.fromIterable(values);
    }

    /**
     * @description: 路由新增
     * @author: guohui13
     * @date: 2022/9/19 20:00
     * @param:
     * @return:
     **/
    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(r -> {
            RouteDefinitionVo vo = new RouteDefinitionVo();
            BeanUtils.copyProperties(r, vo);
            System.out.println("保存路由信息{}" + vo);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.opsForHash().put("gateway_route_key", r.getId(), vo);
            redisTemplate.convertAndSend("gateway_jvm_route_reload_topic", "新增路由信息,网关缓存更新");
            return Mono.empty();
        });
    }

    /**
     * @description: 路由删除
     * @author: guohui13
     * @date: 2022/9/19 20:00
     * @param:
     * @return:
     **/
    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        routeId.subscribe(id -> {
            System.out.println("删除路由信息" + id);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.opsForHash().delete("gateway_route_key", id);
        });
        redisTemplate.convertAndSend("gateway_jvm_route_reload_topic", "删除路由信息,网关缓存更新");
        return Mono.empty();
    }
}
